"""
Author: Meng
Date: 2018/7/12
"""
from app.models.share.shareList import ShareKey, ShareShip
from app.models.cloud.folder import DiskFile, DiskFolder
from app.models.admin.config import FConfig
from app.models.admin.user import User
from flask_restful import Resource, reqparse, fields
from app.api import api
from f_lib.principal.auth import auth_token
from datetime import datetime, timedelta
from f_lib.code import Msg
from flask import g, make_response
from datetime import datetime
from f_lib.marshal_list import marshal
import os
from settings import UPLOAD_PATH, PUBLIC_UPLOAD_PATH
import urllib.parse
from f_lib.tool.time import strf_time
from f_lib.principal.safety import safety_strategy


class ShareCreate(Resource):
    l_parse = reqparse.RequestParser()
    l_parse.add_argument('list', required=True, type=dict, action='append')

    @safety_strategy
    @auth_token()
    def post(self):
        arg = self.l_parse.parse_args()
        config = FConfig.query_one()
        # print(config)
        expired = datetime.now() + timedelta(days=config.share_expired)
        user = g.user
        share = ShareKey(user_id=user.id, share_user=user.name, expired=expired, is_always=config.share_always)
        share_key = share.share_key
        share_list = arg.get('list')
        for sh in share_list:
            sh['share_key'] = share_key
            sh['type_id'] = sh['id']
            sh.pop('id')
            ss = ShareShip(**sh)
            ss.save()

        share.save()
        return Msg.success('ok', share_key=share.share_key, expired=strf_time(expired), share_host=config.share_host)


class ShareCreateOne(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('type', required=True, type=str)
    parse.add_argument('id', required=True, type=str)

    @safety_strategy
    @auth_token()
    def post(self):
        arg = self.parse.parse_args()
        config = FConfig.query_one()
        expired = datetime.now() + timedelta(days=config.share_expired)
        user = g.user
        share = ShareKey(user_id=user.id, share_user=user.name, expired=expired, is_always=config.share_always)
        arg['share_key'] = share.share_key
        arg['type_id'] = arg['id']
        arg['user_id'] = user.id
        arg.pop('id')
        ShareShip.create(**arg)
        share.save()
        return Msg.success('ok', share_key=share.share_key, expired=strf_time(expired), share_host=config.share_host)


class ShareBase(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('share_key', required=True, type=str)

    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        share = ShareKey.query_one(**arg)
        now = datetime.now()
        if share:
            if share.expired > now:
                share_list = ShareShip.query_many(**arg)
                folder_list = []
                file_list = []
                for item in share_list:
                    if item.type == 'file':
                        file = DiskFile.get_by_id(item.type_id)
                        file_list.append({
                            'name': file.name,
                            'id': file.id,
                            'type': 'file',
                            'file_size': file.file_size,
                            'file_name': file.file_name
                        })
                    elif item.type == 'folder':
                        folder = DiskFolder.get_by_id(item.type_id)
                        folder_list.append({
                            'name': folder.name,
                            'type': 'folder',
                            'id': folder.id
                        })
                return Msg.success('ok', path=folder_list + file_list, expired=share.expired.strftime('%Y-%m-%d'),
                                   share_user=share.share_user)
            else:
                return Msg.failed_dict(1004)
        else:
            return Msg.failed_dict(1004)


folder_fields = {
    'id': fields.Integer,
    'name': fields.String,
    'type': fields.String
}
file_fields = {
    'id': fields.Integer,
    'name': fields.String,
    'type': fields.String,
    'file_size': fields.Integer,
    'file_name': fields.String
}


class ShareList(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('share_key', type=str, required=True)
    parse.add_argument('id', type=int, required=True)
    parse.add_argument('b_id', type=int, required=True)

    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        share = ShareKey.query_one(share_key=arg['share_key'])
        now = datetime.now()
        if share:
            if share.expired > now:
                share_list = ShareShip.query_many(share_key=arg['share_key'])
                if arg['b_id'] in [item.type_id for item in share_list]:
                    if arg['id'] != arg['b_id']:
                        b_folder = DiskFolder.get_by_id(arg['b_id'])
                        fos = DiskFolder.get_by_id(arg['id'])

                        if fos.folder_path.startswith(b_folder.folder_path):
                            t_id = arg['id']
                        else:
                            return Msg.failed_dict(1004)
                    else:
                        t_id = arg['b_id']

                    folder = DiskFolder.get_by_id(t_id)
                    folder_path = folder.folder_path + '/' + folder.name if folder.folder_path != '/' else '/' + folder.name
                    print(folder_path)
                    fo = DiskFolder.query_many(folder_path=folder_path, user_id=share.user_id)
                    fi = DiskFile.query_many(folder_path=folder_path, user_id=share.user_id)
                    mf = marshal(folder_fields, fo)
                    mi = marshal(file_fields, fi)
                    return Msg.success(path=mf + mi)

                else:
                    return Msg.failed_dict(400)
            else:
                return Msg.failed_dict(1004)
        else:
            return Msg.failed_dict(1003)


class ShareFile(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('share_key', type=str, required=True)

    @safety_strategy
    def get(self, filename=None):
        arg = self.parse.parse_args()
        share = ShareKey.query_one(**arg)
        if share:
            file = DiskFile.query_one(file_name=filename)
            user = User.get_by_id(share.user_id)
            save_path = os.path.join(UPLOAD_PATH, user.use_folder)
            path = os.path.join(PUBLIC_UPLOAD_PATH, filename)
            with open(path, 'rb') as f:
                data = f.read()
            resp = make_response(data)
            # print(len(data))
            name = urllib.parse.quote(file.name)

            resp.headers["Content-Disposition"] = f"attachment; filename*=utf-8''{name}"
            resp.headers["Content-Type"] = f"application/octet-stream; charset=utf-8"

            return resp
        else:
            return Msg.failed_dict(1003)


api.add_resource(ShareCreate, '/share/add/repeat', 'fr_share')
api.add_resource(ShareCreateOne, '/share/add', 'f_share')
api.add_resource(ShareBase, '/share/key', 'fb_share')
api.add_resource(ShareList, '/share/path', 'fl_share')
api.add_resource(ShareFile, '/share/file/<string:filename>', 'ff_share')
